function new_struct = guiparam(h_fig, old_struct, struct_index);

% GUIPARAM - obtain parameters from GUI objects
%
%   NEW = GUIPARAM(H_FIG, OLD) obtains values from UICONTROL objects
%   on the figure H_FIG whose Tag values correspond to fieldnames in
%   the structure OLD.  The values in the structure are updated and
%   returned as NEW.
%
%   NEW = GUIPARAM(H_FIG, OLD, INDEX) updates field values in the
%   structure array element OLD(INDEX).
%
%   If a scalar value is stored in the UICONTROL object, its value
%   can be stored as an element of a vector in the structure:
%
%             NEW(INDEX).FIELD(ELEMENT) = VALUE
%
%   where FIELD = get(h_obj, 'Tag'), ELEMENT = get(h_obj, 'UserData'),
%   and VALUE = get(h_obj, 'Value') or str2num(get(h_obj, 'String')).

% initialize output

new_struct = old_struct;

% validate input arguments

if ((nargin < 2) | (nargin > 3))
   msgbox('Invalid number of arguments', 'GUIPARAM Error', 'warn');
   return
elseif (~istype(h_fig, 'figure'))
   msgbox('H_FIG must be a valid figure handle', 'GUIPARAM Error', 'warn');
   return
elseif (~isstruct(old_struct) | isempty(old_struct))
   msgbox('OLD must be a structure', 'GUIPARAM Error', 'warn');
   return
elseif (nargin == 2)
   struct_index = 1;
elseif (~isscalar(struct_index))
   msgbox('INDEX must be a scalar', 'GUIPARAM Error', 'warn');
   return
end

% obtain object handles

h_obj = mfindobj(h_fig, 'Type', 'uicontrol', 'Tag', fieldnames(new_struct));
if (isempty(h_obj))
   return
end

% obtain data values from String/Value property
% obtain array index from UserData property

for i = 1 : length(h_obj)
   switch (get(h_obj(i), 'Style'))
   case {'edit', 'frame', 'pushbutton', 'text'}
      data_value = str2num(get(h_obj(i), 'String'));
   otherwise
      data_value = get(h_obj(i), 'Value');
   end
   array_index = get(h_obj(i), 'UserData');
   
   % if data value & array index are scalar, store value as array element in field
   % otherwise data value is stored as the entire field
   
   if (isscalar(array_index) & isscalar(data_value))
      new_struct = setfield(new_struct, {struct_index}, get(h_obj(i), 'Tag'), {array_index}, data_value);
   else
      new_struct = setfield(new_struct, {struct_index}, get(h_obj(i), 'Tag'), data_value);
   end
end
return
